package devicedbgui;

import devicedbgui.data.BuildDAO;
import devicedbgui.data.DBConnection;
import devicedbgui.data.TestData;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.sql.Connection;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.ImageIcon;
  

/**
 * Program controller. Responsible for displaying main layout of the GUI
 */
 
public class GUI implements ActionListener {
    
     /** Builds frame to display application */
    public JFrame frame = new JFrame(); 
    /** Creates tabs for displaying various information */
    JTabbedPane tab = new JTabbedPane();
    /** Desired exe file to run test cases from */
    private File exefile;
    /** Panel to Show Device Records */
    private DevicePanel pnlDevice;
    /** Menu item to connect to database */
    private JMenuItem connect2DB;
    /** Toolbar button to connect to database */
    private JButton cnt;
    private Process process = null;
     /** Tests if connected to database */    
    public Connection connection = null;
    /** Stores Auto-Login information: Server name */
    public String serverName;
     /** Stores Auto-Login information: User name */
    public String userName;
     /** Stores Auto-Login information: Passwor */
    public String password;
     /** Stores Login information: Schema */
    public String schema;
    /** Stores filename of opened file */
    public String Filename;
     /**  Stores path to test case exe file */
    public static String path;
    /** Verifies whether test cases have been selected */
    public static boolean testloaded = false;
    /** Tests if there were any errors in test cases */
    public boolean error=false;
    /** Stores log in credentials for auto login feature */
    public static final String fileName = "credentials.txt";
    /** Stores data obtain from test case execution */
    public TestData testData = null;
    /** Stores device record of currently setup device */
    private String deviceRecord = "(select an item)";
    /** Stores build id of currently setup device */
    private String buildId = "(select an item)";
    /** Stores exe id of more recently executed exe file */
    private String exeId="";
    /** Stores test case id */
    private String testCaseId="";
   /** Stores device information **/
    public String[]  ar={"","",""};
    
      
     /**
     * Constructor for GUI class: initialises graphical interface
     */

    public GUI() {
  
      // close frame and clean up ini files created
        frame.addWindowListener(new WindowAdapter(){
            @Override
      public void windowClosing(WindowEvent we){
        delfile del=new delfile();
        String userDir = System.getProperty("user.dir");
        del.deleteFiles(userDir);    
         System.exit(0);   
        
      }});

        /* Setup Toolbar */
        Toolbar();
        /* Setup Menubar */
        Menubar();
        //TestResults(); 
        pnlDevice = new DevicePanel(this);
        
        frame.add(tab);

        // check auto login and fill data
        if (checkAutoLogin()) {
            try {
                connection = DBConnection.getConnection(serverName, userName, password, schema);
                pnlDevice.fillAllRecords();

            } catch (Exception e) {
                JOptionPane.showMessageDialog(frame, "Cannot automatically login to server");
                connection = null;

            }
        }
        
                
        Dimension minimumSize = new Dimension(900,600);
        frame.setMinimumSize(minimumSize);
        frame.setTitle("BogozmaBench");
        frame.setSize(800, 600);
        frame.setLocationRelativeTo(null);
        frame.setExtendedState(frame.getExtendedState()|JFrame.MAXIMIZED_BOTH);
        frame.setVisible(true);
    }
/**
 * Checks if auto login feature is enabled and fills in required info
 * @return true if auto- login credentials found else false
 */
    public boolean checkAutoLogin() {
        File file = new File(fileName);
        if (!file.exists()) {
            return false;
        } else { //read file

            try {
                BufferedReader br = new BufferedReader(new FileReader(fileName));
                // read autologin
                String first = br.readLine(); // autologin=

                String[] tmp = first.split("=");
                if (tmp.length != 2 || !tmp[0].equalsIgnoreCase("autologin")) {
                    return false;
                }
                if (!tmp[1].equalsIgnoreCase("1")) {
                    return false;
                // read server
                }
                String second = br.readLine(); // server=

                tmp = second.split("=");
                if (tmp.length != 2 || !tmp[0].equalsIgnoreCase("server")) {
                    return false;
                }
                this.serverName = tmp[1];

                // read username
                String third = br.readLine(); // username=

                tmp = third.split("=");
                if (tmp.length != 2 || !tmp[0].equalsIgnoreCase("username")) {
                    return false;
                }
                this.userName = tmp[1];

                // read password
                String fourth = br.readLine(); // password=

                if (fourth.equalsIgnoreCase("password=")) // empty password
                {
                    this.password = "";
                } else {
                    tmp = fourth.split("=");
                    if (tmp.length != 2 || !tmp[0].equalsIgnoreCase("password")) {
                        return false;
                    }
                    this.password = tmp[1];
                }

                // read schema
                String fifth = br.readLine(); // schema=

                tmp = fifth.split("=");
                if (tmp.length != 2 || !tmp[0].equalsIgnoreCase("schema")) {
                    return false;
                }
                this.schema = tmp[1];

                br.close();
            } catch (Exception ex) {
                return false;
            }
        }
        return true;
    }
    /** Connects to database
     * @param e 
     */
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        if (source.equals(connect2DB) || source.equals(cnt)) {
            LoginDBDlg dlg = null;
            if (connection != null) // already connected, show login dialog with prefilled data
            {
                dlg = new LoginDBDlg(frame, serverName, userName, password, schema, true);
            } else {
                dlg = new LoginDBDlg(frame, true);
            }
            dlg.setVisible(true);
            if (dlg.connection != null) {// connect successful
                
                // store connection info
                serverName = dlg.serverName;
                userName = dlg.userName;
                password = dlg.password;
                schema = dlg.schema;
                connection = dlg.connection;
                dlg.dispose();
        pnlDevice.fillAllRecords();
        tab.addTab("", pnlDevice);
        tab.setSelectedComponent(pnlDevice);
        tab.setTabComponentAt( tab.getSelectedIndex(), TabSet("Database Records") );
            }
        }
       
    }
/** Initialises menubar for application */
    private void Menubar() {
        JMenuBar menubar = new JMenuBar();

        JMenu file = new JMenu("File");
        file.setMnemonic(KeyEvent.VK_F);
        menubar.add(file);

        JMenu settings = new JMenu("Settings");
        settings.setMnemonic(KeyEvent.VK_E);
        menubar.add(settings);

        JMenu db = new JMenu("Database");
        db.setMnemonic(KeyEvent.VK_D);
        menubar.add(db);

        JMenu help = new JMenu("Help");
        help.setMnemonic(KeyEvent.VK_H);
        menubar.add(help);
        
        ImageIcon recordsIcon = createImageIcon("images/dbrec.png");
        JMenuItem records = new JMenuItem("View Records",recordsIcon);
        records.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent event) {
                if (connection != null) {
                    pnlDevice.fillAllRecords();
                    tab.addTab("", pnlDevice);
                    tab.setSelectedComponent(pnlDevice);
                    tab.setTabComponentAt( tab.getSelectedIndex(), TabSet("Database Records") );
                    
                    
                } else {
                    JOptionPane.showMessageDialog(new JFrame(), "Not Connected to Database!",
                            "Error 1", JOptionPane.ERROR_MESSAGE);
                }


            }
        });
        db.add(records);
        ImageIcon connect2DBIcon = createImageIcon("images/connect.png");
        connect2DB = new JMenuItem("Connect to database",connect2DBIcon);
        connect2DB.addActionListener(this);
        db.add(connect2DB);

        ImageIcon manualIcon = createImageIcon("images/manual.png");
        JMenuItem manual = new JMenuItem("User's Manual",manualIcon);
        manual.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent event){
                try {
                    Runtime.getRuntime().exec("cmd /c \"" + "UserManual.pdf" + "\"");
                } catch (IOException ex) {
                    Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
                }

        }});
       

        help.add(manual);
        ImageIcon aboutIcon = createImageIcon("images/about.png");
        JMenuItem about = new JMenuItem("About",aboutIcon);
        help.add(about);
        about.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent event){
           JOptionPane.showMessageDialog (null, "                  BogozmaBench\n\nCreators:\nPoulami Sanyal, Noemiliza Lanuzo,\nNed Lee, Amin Salem", "About", JOptionPane.PLAIN_MESSAGE);
        }});
        
        ImageIcon devWizIcon = createImageIcon("images/setup.png");
        JMenuItem deviceWiz = new JMenuItem("Setup Wizard", devWizIcon);
        file.add(deviceWiz);
        
        //Select test cases
        ImageIcon newTestIcon = createImageIcon("images/test.png");
        JMenuItem newTest = new JMenuItem("Select Test Cases",newTestIcon);
        file.add(newTest);
        newTest.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
            RunEXECActionPerformed(event);
            }
        });

        JMenuItem fileClose = new JMenuItem("Exit");
        file.add(fileClose);

        //Displays Device information
        ImageIcon devInfoIcon = createImageIcon("images/device.png");
        JMenuItem devInfo = new JMenuItem("Device Information",devInfoIcon);
        settings.add(devInfo);
        devInfo.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent event) {
         DeviceInfoDlg dlg= new DeviceInfoDlg(pnlDevice, deviceRecord, buildId,ar,true);
         dlg.setLocationRelativeTo(null);
         dlg.setVisible(true);
            }});
        
        
        

       deviceWiz.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent event) {
            if (connection != null) {
                if (NewDeviceWiz()){
                tab.addTab("", pnlDevice);
                tab.setSelectedComponent(pnlDevice);
                tab.setTabComponentAt( tab.getSelectedIndex(), TabSet("Database Records") );
                
                }
            }
            else {
                   JOptionPane.showMessageDialog(new JFrame(), "Not Connected to Database!",
                   "Error 1", JOptionPane.ERROR_MESSAGE);
                }
            }});
            
        fileClose.setToolTipText("Exit application");
        fileClose.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent event) {
        delfile del=new delfile();
        String userDir = System.getProperty("user.dir");
        del.deleteFiles(userDir);    
            System.exit(0);     
             
            }
        });

        frame.setJMenuBar(menubar);
    }
/** Initialises toolbar for application*/
    private void Toolbar() {
        JToolBar toolbar = new JToolBar();
        ImageIcon cntIcon = createImageIcon("images/connect.png");
        cnt = new JButton("Connect",cntIcon);
        cnt.setMnemonic(KeyEvent.VK_C);
        cnt.addActionListener(this);
        toolbar.add(cnt);
    
        //Creates device wizard for creating new device record or selecting an existing  one
        ImageIcon devWizIcon = createImageIcon("images/setup.png");
        JButton devWiz = new JButton("Setup Wizard",devWizIcon);
        devWiz.setMnemonic(KeyEvent.VK_P);
        devWiz.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
             if (connection != null) {
                if (NewDeviceWiz())
                { tab.addTab("", pnlDevice);
                  tab.setSelectedComponent(pnlDevice);
                  tab.setTabComponentAt( tab.getSelectedIndex(), TabSet("Database Records") );
                
                    }
            }
                else {
                    JOptionPane.showMessageDialog(new JFrame(), "Not Connected to Database!",
                            "Error 1", JOptionPane.ERROR_MESSAGE);
                }
            }
        });
        toolbar.add(devWiz);
        
        //Select Test Cases
        ImageIcon selectTestIcon = createImageIcon("images/test.png");
        JButton selectTest = new JButton("Select Test Cases",selectTestIcon);
        selectTest.setMnemonic(KeyEvent.VK_T);
        selectTest.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
              // RunEXEActionPerformed(e);
                RunEXECActionPerformed(e);
            }
        });
        toolbar.add(selectTest);
     
      
        ImageIcon recordsIcon = createImageIcon("images/dbrec.png");
        JButton rec = new JButton("View Records",recordsIcon);
        rec.setMnemonic(KeyEvent.VK_V);
        rec.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent event) {
                if (connection != null) {
                    
                    tab.addTab("",pnlDevice);
                    tab.setSelectedComponent(pnlDevice);
                    tab.setTabComponentAt( tab.getSelectedIndex(), TabSet("Database Records") );
                    
                    
                } else {
                    JOptionPane.showMessageDialog(new JFrame(), "Not Connected to Database!",
                            "Error 1", JOptionPane.ERROR_MESSAGE);
                }}});
        toolbar.add(rec);
               
        frame.getContentPane().add(toolbar, BorderLayout.NORTH);
    }
     private void RunEXECActionPerformed(java.awt.event.ActionEvent event) {
        error=false;
        ArrayList<String> ar;
        JFileChooser fileChooser = new JFileChooser(".");
        fileChooser.setApproveButtonText("Select");
        fileChooser.setDialogTitle("Select an executable file");
        fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
        fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        fileChooser.setFileFilter(new FileFilter() {

            public boolean accept(File f) {
                return f.getName().toLowerCase().endsWith(".exe") || f.isDirectory();
            }
            public String getDescription() {
                return "Executable Files";
            }
        });
        if (fileChooser.showOpenDialog(new JFrame()) == JFileChooser.APPROVE_OPTION) {
            exefile = fileChooser.getSelectedFile();
            if(exefile.isFile()){RunEXEFILE();}
            else if(exefile.isDirectory()){RunEXEDIR();}
           
         }
       
    }
   /** Runs single executable test case files */
    private void RunEXEFILE() {
  ArrayList<String> ar;
        if (!exefile.getName().endsWith(".exe")) {
                JOptionPane.showMessageDialog(new JFrame(), "Please select an executable file.");
            } else {
                path = exefile.getPath();
                Filename = exefile.getAbsolutePath();

                try {

                    ar = new ArrayList<String>();
                    ar.add(exefile.getPath());
                    ar.add("list");
                    System.out.print(ar);
                    String[] stringArray = (String[]) ar.toArray(new String[ar.size()]);

                    process = Runtime.getRuntime().exec(stringArray);
                    try {
                        process.waitFor();
 
                    } catch (InterruptedException ex) {
                        Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
                    }

                    JDialog f = new ListTC(new JFrame(),exefile.getName());
                    f.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
                }
            // read from the called program's standard output stream

            }
            if(testloaded==true){
            loadResults();}
        
    }
     /** Runs all executable test case files in a folder*/
    private void RunEXEDIR() {
        error=false;
        ArrayList f1= new ArrayList<String>();
        ArrayList f2= new ArrayList<String>();  
        ArrayList<String> ar;
         
        
        File folder = new File(String.valueOf(exefile));
        File[] listOfFiles = folder.listFiles(); 
        String files;

        for (int i = 0; i < listOfFiles.length; i++) 
        { 
            if (listOfFiles[i].isFile()) 
            {
                files = listOfFiles[i].getName();
               if (files.endsWith(".exe") || files.endsWith(".EXE"))
                {
                    System.out.println(exefile.getAbsoluteFile()+"\\"+listOfFiles[i].getName());
                    f2.add(listOfFiles[i].getName());
                    f1.add(exefile.getAbsoluteFile()+"\\"+listOfFiles[i].getName());
                }
            }
        }
    
        TCDlg t=new TCDlg(new JFrame());
    
        for (int i=0; i<f1.size(); i++){
           try {
                    ar = new ArrayList<String>();
                    ar.add((String) f1.get(i));
                    path = (String)f1.get(i);
                    ar.add("list");
                    System.out.println(ar);
                    String[] stringArray = (String[]) ar.toArray(new String[ar.size()]);

                    process = Runtime.getRuntime().exec(stringArray);
                    try {
                        process.waitFor();
 
                    } catch (InterruptedException ex) {
                        Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
                    }

                    ListTCPanel pane=new ListTCPanel((String)f2.get(i));
                    t.tbpane.addTab((String)f2.get(i),pane);
                
                } catch (IOException ex) {
                    Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
                }
            // read from the called program's standard output stream
}
            
            
    t.setVisible(true);

    for (int i=0; i<f2.size(); i++){
        // System.out.println("record: "+deviceRecord);
        File ex =new File((String)f1.get(i));
        TCResPanel pn= new TCResPanel(ex, this);
 
        if(pn.Notrun==false){
        tab.addTab("", pn);
        tab.setSelectedComponent(pn);
        tab.setTabComponentAt( tab.getSelectedIndex(), TabSet((String)f2.get(i)) );
        }
 
    }
         
    }
 
    /** Sets up device record and build id for storing information to database 
     * @return true or false based on whether wizard was completed or not
     */
public boolean NewDeviceWiz(){
    boolean retvalue;
    SetupWizard d= new SetupWizard(this,pnlDevice, null, true);
    d.setVisible(true);
    
    
    if (!d.cancel){
      BuildDAO dd = new BuildDAO(connection);
        if(d.getMode()==1){
                try {
                    buildId = String.valueOf(dd.selectByDevice(deviceRecord).get(0).idBuild);
                } catch (Exception ex) {
                    Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
                }
        }
        else if(d.getMode()==2)
             {buildId=d.getBuild();}
        retvalue=true;
    }
    else {retvalue=false;}
    if (d.isModifiedDB) {
       pnlDevice.fillAllRecords();
    }
    return retvalue;
}
/** Displays test results in new tab*/
    public void loadResults() {
       
        System.out.println("record: "+deviceRecord);
        TCResPanel pn= new TCResPanel(exefile, this);
        
        if(pn.Notrun==false){
        tab.addTab("", pn);
        tab.setSelectedComponent(pn);
        tab.setTabComponentAt( tab.getSelectedIndex(), TabSet(exefile.getName()) );
        }
        
        
    }
  /*    Creates close button on tabs
     * @param str   Title of tab
     * @return  Jpanel to be added to tabbed pane
     */
    public JPanel TabSet(String str){
       JPanel tabclose = new JPanel();
        tabclose.setOpaque(false);
        tabclose.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
      
        tabclose.add(new JLabel( str ));
        ImageIcon closeIcon = createImageIcon("images/tabcloseb2.png");
        JButton button = new JButton(closeIcon);
        button.setMnemonic(KeyEvent.VK_W);
        button.setMargin(new java.awt.Insets(2, 10, 0, 0));
        button.setOpaque(false);
        button.setContentAreaFilled(false);
        button.setBorderPainted(false) ;
       
        button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent event) {
             // close the tab which was clicked
                tab.remove(tab.getSelectedComponent());  
        }});

         tabclose.add( button );
        return tabclose;
    }
    
    /** Sets the device record of currently setup device
     * @param devicerecord 
     */
    public void setDeviceRecord(String devicerecord){
    this.deviceRecord=devicerecord;
    }
    /** Gets device record of currently setup device
     * @return deviceRecord
     */
    public String getDeviceRecord(){
    return deviceRecord;
    }
    /** Sets the build id of currently setup device
     * @param buildid 
     */
    public void setBuildId(String buildid){
    this.buildId=buildid;
    }
    /** Gets the build id of currently setup device
     * @return buildId
     */
     public String getBuildId(){
    return buildId;
    }
     /** Sets the exe id of test case exe
     * @param exid 
     */
     public void setExeID(String exid){
         this.exeId=exid;
     }
     /** Gets the exe id of current test case
     * @return exeId 
     */
     public String getExeID(){
         return exeId;
     }
     /** Sets the test case id of current test case
      * @param td 
     */
      public void setTestCaseID(String td){
         this.testCaseId=td;
     }
     /** Gets the test case id of current test case
      * @return testCaseId
      */
      public String getTestCaseID(){
         return testCaseId;
     }
      /** Sets the current device info
     */
      public void setDeviceInfo(String dr, String MAC, String Serial, String Name) {
          this.deviceRecord=dr;
          
          ar[0]=MAC;
          ar[1]=Serial; 
          ar[2]=Name;
    
        
       }
     
    
      /** Creates an image icon that is used by menu items and toolbar buttons
       *  @param path   location of image file
       *  @return image at specified url
       */
    protected static ImageIcon createImageIcon(String path) {
        java.net.URL imgURL = GUI.class.getResource(path);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }


    public static void main(String[] args) {

        new GUI();
  
    }
}